<?php
// Исключаем прямой доступ
defined('_JEXEC') or die('Restricted access');

// Подключаем библиотеки
jimport('joomla.filesystem.file');

class UpdaterCBR {

	// Объявляем переменные
	public $ok = true;

	protected $updater;
	protected $date;

	protected $url;
	protected $data = array();
	protected $numbers = array();
	protected $msg;

	// Точка входа 
	public function update($id) {

		// Инициализируем переменные
		$db =& JFactory::getDBO();

		// Получаем всю необходимую информацию о загрузчике
		$query = "SELECT * FROM `#__pricer_robot` WHERE `#__pricer_robot`.`id` = $id;";
		$db->setQuery($query);
		$this->updater = $db->loadObject();

		// Определяем дату
		if (true != $this->date = $this->getDate()) { return false; }

		// Определяем URL
		if (true != $this->url = $this->getURL()) { return false; }

		// Загружаем данные в массив
		if (true != $this->data = $this->getData()) { return false; }

		// Идентифицируем колонки в массиве с данными
		if (true != $this->numbers = $this->getNumbers()) { return false; }

		// Проходим по столбцам, загружаем в базу
		if (true != $this->onParsing()) { return false; }

		// Отмечаем время обновления
		if (true != $this->setUpdated()) { return false; }
	}

	// Возвращает сегодняшнюю дату в формате 2012-12-21
	protected function getDate() {

		// Определяем дату
		$date = getdate();

		// Правим день и месяц
		if ($date['mon'] < 10) {
			$date['mon'] = '0'.$date['mon'];
		}
		if ($date['mday'] < 10) {
			$date['mday'] = '0'.$date['mday'];
		}

		// Формируем дату и возвращаем результат
		$date = "{$date['year']}-{$date['mon']}-{$date['mday']}";
		return $date;
	}

	// Возвращает адрес, по которому доступно обновление
	protected function getURL() {

		// Определяем дату
		$date = getdate();

		// Правим день и месяц
		if ($date['mon'] < 10) {
			$date['mon'] = '0'.$date['mon'];
		}
		if ($date['mday'] < 10) {
			$date['mday'] = '0'.$date['mday'];
		}

		// Формируем URL и возвращаем результат
		$url = "http://cbr.ru/eng/currency_base/D_print.aspx?date_req={$date['mday']}.{$date['mon']}.{$date['year']}";
		return $url;
	}

	// Возвращает массив данных
	protected function getData() {
		$dom = new DomDocument();
		$dom->loadHtmlFile($this->url);
		$row = 0;
		$xpath = new DOMXPath($dom);
		foreach ($xpath->query('//table[@class = "CBRTBL"]/tr') as $tr) {
			$col = 0;
			foreach ($tr->childNodes as $td) {
				$data[$row][$col] = $td->nodeValue;
//				$this->addMsg("\$data[{$row}][{$col}] = {$data[$row][$col]}");
				$col++;
			}
			$row++;
		}
		return $data;
	}

	// Возвращает массив номеров колонок
	protected function getNumbers() {
		for ($col=0; $col<sizeof($this->data[0]); $col++) {
			switch ($this->data[0][$col]) {
				case 'Num Ñode'  : $numbers['code']	  = $col+0; break;
				case 'Char Ñode' : $numbers['alias']    = $col+1; break;
				case 'Unit'        : $numbers['quantity'] = $col+2; break;
				case 'Currency'    : $numbers['name']     = $col+3; break;
				case 'Rate'        : $numbers['rate']     = $col+4; break;
			}
		}
//		$this->addMsg("{$numbers['code']} = \$numbers['code']");
//		$this->addMsg("{$numbers['alias']} = \$numbers['alias']");
//		$this->addMsg("{$numbers['quantity']} = \$numbers['quantity']");
//		$this->addMsg("{$numbers['name']} = \$numbers['name']");
//		$this->addMsg("{$numbers['rate']} = \$numbers['rate']");
		if ((0 === $numbers['code'])
			and (2 == $numbers['alias'])
			and (4 == $numbers['quantity'])
			and (6 == $numbers['name'])
			and (8 == $numbers['rate'])) {
			return $numbers;
		} else {
			$this->addMsg('Формат выгрузки курсов валют изменился - необходима доработка парсера.');
			return false;
		}
	}

	// Загружает информацию в базу банных
	protected function onParsing() {
	
		// Подключаемся к базе
		$db =& JFactory::getDBO();

		// Цикл по всем строкам
		for ($row=1; $row<sizeof($this->data); $row++) {

			// Определяем переменные
			$code = $this->getCode($row);
			$quantity = $this->getQuantity($row);
			$name = $this->getName($row);
			$alias = $this->getAlias($row, $name);
			$rate = $this->getRate($row);
			// Проверяем, есть ли курс на текущую дату
			$query = "
				SELECT rate
				FROM #__pricer_currency_rate
				WHERE
					#__pricer_currency_rate.currency_alias = '{$alias}' AND
					#__pricer_currency_rate.date = '{$this->date}';
			";
//			$this->addMsg($query);
			$db->setQuery($query);
			$rateOnSQL = $db->loadResult();
			if (true == $rateOnSQL) { // Курс валюты на текущее число уже есть
				$this->addMsg("Курс валюты {$alias} на текущую дату уже есть.");
			} else { // Курс валюты на текущее число отсутствует
				// Помечаем устаревшие курсы
				$this->setZeroState($alias);
				// Заносим информацию в базу
				$query = "INSERT INTO #__pricer_currency_rate (`currency_alias`, `date`, `rate`, `quantity`, `state`, `created`, `created_by`, `modified`, `modified_by`) VALUES ('{$alias}', '{$this->date}', '{$rate}', '{$quantity}', '1', NOW(), '1', NOW(), '1');";
				$db->setQuery($query);
				$db->query();
			}
		}
		return true;
	}

	protected function getCode($row) {
		$code = $this->data[$row][$this->numbers['code']];
		return $code;
	}

	protected function getQuantity($row) {
		$quantity = $this->data[$row][$this->numbers['quantity']];
		return $quantity;
	}

	protected function getName($row) {
		$name = $this->data[$row][$this->numbers['name']];
		return $name;
	}

	// Выполнять только после определения имени
	protected function getAlias($row, $name) {

		// Подключаемся к базе
		$db =& JFactory::getDBO();

		// Получаем значение и чистим его от мусора
		$alias = $this->data[$row][$this->numbers['alias']];
		$alias = $this->clearAlias($alias);

		// Проверяем по буквенному коду - есть ли валюта в базе
		$query = "SELECT id FROM #__pricer_currency WHERE '{$alias}' <=> #__pricer_currency.alias;";
		$db->setQuery($query);
		$id = $db->loadResult();
		if (true == $id) { // Есть такая валюта, возвращаем буквеный код
			return $alias;
		} else { // Нет такой валюты, добавляем
			$query = "INSERT INTO #__pricer_currency (`id`, `title`, `alias`, `name_html`, `state`, `description`, `created`, `created_by`, `modified`, `modified_by`) VALUES (0, '{$name}', '{$alias}', '{$alias}', '1', '', NOW(), '0', NOW(), '0');";
//			$this->addMsg($query);
			$db->setQuery($query);
			$db->query();

//			// Проверяем наличие после добавления
			$query = "SELECT id FROM #__pricer_currency WHERE '{$alias}' <=> #__pricer_currency.alias;";
			$db->setQuery($query);
			$id = $db->loadResult();
			if (true == $id) { // Есть такая валюта, возвращаем код
				$this->addMsg("Добавлена валюта {$alias}.");
				return $alias;
			} else { // Нет такой валюты, фиксируем ошибку при добавлении
				$this->addMsg("Добавить валюту {$alias} не удалось.");
				return false;
			}
		}
	}

	// Чистит буквенный код валюты
	protected function clearAlias($alias) {
		$alias = ereg_replace('[^A-Z]*', '', $alias);
		if (3 == strlen($alias)) {
			return $alias;
		} else {
			return false;
		}
	}

	protected function getRate($row) {
		$rate = $this->data[$row][$this->numbers['rate']];
		$rate = $this->clearRate($rate);
		return $rate;
	}

	// Снятие с публикации устаревших курсов валют
	protected function setZeroState($alias) {
		$db =& JFactory::getDBO();
		$query = "UPDATE `#__pricer_currency_rate` SET state = '0' WHERE `currency_alias` = '{$alias}';";
		// $this->addMsg($query);
		$db->setQuery($query);
		$db->query();
		return true;
	}


	// Преобразует курс в удобоваримый для базы вид
	protected function clearRate($string) {
		$string = ereg_replace('[,]', '.', $string);
		$string = ereg_replace('[ ]', '', $string);
		return doubleval($string);
	}

	// Преобразует количество из строки в число
	protected function clearQuantity($string) {
		$int = ereg_replace('[^0-9]*', '', $string); // убираем из строки все, что не цифра
		if (true == $int) {
			return $int;
		} else {
			$string = utf8_strtolower($string);
			switch ($string) {
				case '0': return 0; // В противном случае нули выбывают из обработки
				default : $this->msg .= 'Необходим новый кейс обработки количества: ['.$string."].\n"; return 0;
			}
		}
	}

	// Отмечает время загрузки
	protected function setUpdated() {
		$db =& JFactory::getDBO();
		$query = "UPDATE `#__pricer_robot` SET `updated` = NOW() WHERE `id` = '{$this->updater->id}';";
		$db->setQuery($query);
		$db->query();
		return true;
	}

	// Возвращает строку сообщений
	public function getMsg() {
		return $this->msg;
	}

	// Добавляет сообщение
	protected function addMsg($msg) {
		$this->msg .= "{$msg}<br/>\n";
	}
}
